package com.mchat.wsserver;


import com.mchat.user.service.IUserService;
import com.mchat.wsserver.handler.AuthHandler;
import com.mchat.wsserver.handler.WebSocketFrameHandler;
import io.jsonwebtoken.JwtParser;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class WebSocketServer {

    public static final int PORT=8090;
    private final EventLoopGroup bossGroup=new NioEventLoopGroup(1);
    private final EventLoopGroup workerGroup=new NioEventLoopGroup();
    public ChannelFuture channelFuture;
    //jwt密钥
    @Value("${jwt.secret}")
    private  String secretKey ;

    @Resource
    private JwtParser parser;
    @Resource
    private IUserService userService;
    String path="/";

    public void run() throws InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        AuthHandler authHandler = new AuthHandler(parser,userService);
        LoggingHandler loggingHandler = new LoggingHandler(LogLevel.INFO);

        this.channelFuture= serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .option(ChannelOption.SO_BACKLOG, 128)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) {
                        socketChannel.pipeline()
                                .addLast(loggingHandler)
                                //120秒客户端没有向服务器发送心跳则关闭连接
                                .addLast(new IdleStateHandler(180, 0, 0))
                                .addLast(new HttpServerCodec())
                                .addLast(new HttpObjectAggregator(8192))
                                .addLast(new WebSocketServerProtocolHandler(path))
                                .addLast(authHandler);

                    }
                }).bind(PORT).sync();
    }
    @PreDestroy
    public void destroy(){
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
    @PostConstruct
    public void start() throws InterruptedException {
        run();
    }
}
